/**
 * 一个简单的VUE模拟器
 */
class VueImitator {
    constructor(VueData) {
        this.initialize(VueData);
    }

    /**
     * 初始化VM数据
     * @param VueData
     */
    initialize = (VueData) => {
        const data = VueData.data();

        //遍历所有的方法
        for (let key in VueData.methods) {
            let value = VueData.methods[key];
            Object.defineProperty(this, key, {
                enumerable: true,
                configurable: true,
                get() {
                    return value;
                },
                set(v) {
                    if (value !== v) value = v;
                }
            });
        }

        let htmlText = document.body.innerHTML;
        //获取所有的mustache文本
        let mustacheText = htmlText.match(/{{.*?}}/g);
        //获取当前DOM元素的子页面
        let DOMChildren = document.body.children;
        //获取DOM数量
        let DOMChildrenCount = document.body.childElementCount;
        for (let c = 0; c < DOMChildrenCount; c++) {
            let DOM = DOMChildren[c];
            if (DOM.localName !== 'script') {//DOM.nodeName代表当前DOM元素的标签名称
                console.log(DOM.nodeName);
                console.log(DOM.innerText);

                //获取所有的属性名
                let attrNames = DOM.getAttributeNames();
                attrNames.forEach(aName => {
                    let attributeNode = DOM.getAttributeNode(aName);
                    let localName = attributeNode.localName; //id等其他属性值
                    let value = attributeNode.value; //值

                    if (localName.match(/^v-on/) !== null) {
                        let vOnFunction = localName.replace(/v-on:/, '');
                        let vd = VueData;
                        switch (vOnFunction) {
                            case 'click':
                                DOM.onclick = () => {
                                    this[value](this);
                                };
                                break;
                        }
                        console.log(`${localName}: ${value}`);
                    } else if (localName.match(/^v-html/) !== null) { //v-html的使用
                        Object.defineProperty(this, value, {
                            enumerable: true,
                            configurable: true,
                            get() {
                                return value;
                            },
                            set(v) {
                                if (value === v) return;
                                value = v;
                                DOM.innerHTML = value;
                            }
                        });
                    }
                });

                let innerText = DOM.innerText;
                let innerHTML = DOM.innerHTML;

                //发现双大括号中的vue变量，应采用正则表达式
                let vueKeys1 = innerText.match(/{{.*?}}/g);

                if (vueKeys1 === null) continue;

                let vueKeys2 = vueKeys1.map(v => v.replace(/[{{]|[}}]/g, ''));
                console.log(vueKeys2);

                vueKeys2.forEach(vueKey => {
                    let currentValue = data[vueKey]; //采用闭包的方式
                    let originalInnerText = innerText;
                    Object.defineProperty(this, vueKey, {
                        enumerable: true,
                        configurable: true,
                        get() {
                            return currentValue;
                        },
                        set(v) {
                            currentValue = v;

                            let currentInnerText = originalInnerText;
                            //重新遍历
                            vueKeys2.forEach(singleVueKey => {
                                if (singleVueKey !== vueKey)
                                currentInnerText =
                                    currentInnerText.replace(`{{${singleVueKey}}}`, this[singleVueKey]);
                            });
                            let replaceValue = `{{${vueKey}}}`;
                            DOM.innerText = currentInnerText.replace(replaceValue, currentValue);
                        }
                    });
                });
            }
        }

        for (let key in data) {
            this[key] = data[key];
        }


    }
}

export default VueImitator;

